﻿using System.Globalization;

namespace UnityMethods.Extend
{
    public static partial class Ext
    {
        public static bool StrEquals(this string value, string data)
        {
            if (value.IsEmpty() && data.IsEmpty())
            {
                return true;
            }

            if (value.IsEmpty() || data.IsEmpty())
            {
                return false;
            }

            return value.Equals(data);
        }

        #region 是否为空

        /// <summary>
        /// 是否为空
        /// </summary>
        /// <param name="value">值</param>
        public static bool IsEmpty(this string value)
        {
            return string.IsNullOrWhiteSpace(value);
        }

        /// <summary>
        /// 是否为空
        /// </summary>
        /// <param name="value">值</param>
        public static bool IsEmpty(this Guid? value)
        {
            if (value == null)
            {
                return true;
            }

            return IsEmpty(value.Value);
        }

        /// <summary>
        /// 是否为空
        /// </summary>
        /// <param name="value">值</param>
        public static bool IsEmpty(this Guid value)
        {
            if (value == Guid.Empty)
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// 是否为空
        /// </summary>
        /// <param name="value">值</param>
        public static bool IsEmpty(this object value)
        {
            if (value != null && !string.IsNullOrEmpty(value.ToString()))
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        #endregion

        /// <summary>
        /// 转换为整型，不成功返回0
        /// </summary>
        /// <param name="data">数据</param>
        public static int ToInt(this object data)
        {
            int result = 0;
            if (data == null)
            {
                return result;
            }

            var success = int.TryParse(data.ToString(), out result);
            if (success)
            {
                return result;
            }
            else
            {
                try
                {
                    return Convert.ToInt32(ToDouble(data, 0));
                }
                catch (Exception)
                {
                    return result;
                }
            }
        }

        /// <summary>
        /// object 转换为整型
        /// </summary>
        /// <param name="data">数据</param>
        public static long ToLong(this object data)
        {
            long result = -1;
            if (data == null)
            {
                return result;
            }

            var success = long.TryParse(data.ToString(), out result);
            if (success)
            {
                return result;
            }
            else
            {
                try
                {
                    return Convert.ToInt64(ToDouble(data, 0));
                }
                catch (Exception)
                {
                    return result;
                }
            }
        }

        /// <summary>
        /// object 转换为可空整型
        /// </summary>
        /// <param name="data">数据</param>
        public static int? ToIntOrNull(this object data)
        {
            if (data == null)
            {
                return null;
            }

            bool isValid = int.TryParse(data.ToString(), out int result);
            if (isValid)
            {
                return result;
            }

            return null;
        }

        /// <summary>
        /// object 转换为单精度浮点数
        /// </summary>
        /// <param name="data">数据</param>
        public static float ToFloat(this object data)
        {
            if (data == null)
            {
                return 0;
            }

            return float.TryParse(data.ToString(), out float result) ? result : 0;
        }

        /// <summary>
        /// object 转换为双精度浮点数
        /// </summary>
        /// <param name="data">数据</param>
        public static double ToDouble(this object data)
        {
            if (data == null)
            {
                return 0;
            }

            return double.TryParse(data.ToString(), out double result) ? result : 0;
        }

        /// <summary>
        /// object 转换为双精度浮点数,并按指定的小数位4舍5入
        /// </summary>
        /// <param name="data">数据</param>
        /// <param name="digits">小数位数</param>
        public static double ToDouble(this object data, int digits)
        {
            return Math.Round(ToDouble(data), digits);
        }

        /// <summary>
        /// object 转换为可空双精度浮点数
        /// </summary>
        /// <param name="data">数据</param>
        public static double? ToDoubleOrNull(this object data)
        {
            if (data == null)
            {
                return null;
            }

            bool isValid = double.TryParse(data.ToString(), out double result);
            if (isValid)
            {
                return result;
            }

            return null;
        }

        /// <summary>
        /// object 转换为高精度浮点数
        /// </summary>
        /// <param name="data">数据</param>
        public static decimal ToDecimal(this object data)
        {
            if (data == null)
            {
                return 0;
            }

            return decimal.TryParse(data.ToString(), out decimal result) ? result : 0;
        }

        /// <summary>
        /// object 转换为高精度浮点数,并按指定的小数位4舍5入
        /// </summary>
        /// <param name="data">数据</param>
        /// <param name="digits">小数位数</param>
        public static decimal ToDecimal(this object data, int digits)
        {
            return Math.Round(ToDecimal(data), digits);
        }

        /// <summary>
        /// object 转换为可空高精度浮点数
        /// </summary>
        /// <param name="data">数据</param>
        public static decimal? ToDecimalOrNull(this object data)
        {
            if (data == null)
            {
                return null;
            }

            bool isValid = decimal.TryParse(data.ToString(), out decimal result);
            if (isValid)
            {
                return result;
            }

            return null;
        }

        /// <summary>
        /// object 转换为可空高精度浮点数,并按指定的小数位4舍5入
        /// </summary>
        /// <param name="data">数据</param>
        /// <param name="digits">小数位数</param>
        public static decimal? ToDecimalOrNull(this object data, int digits)
        {
            var result = ToDecimalOrNull(data);
            if (result == null)
            {
                return null;
            }

            return Math.Round(result.Value, digits);
        }

        /// <summary>
        /// 按指定范围比较，不符合返回指定值
        /// </summary>
        /// <param name="data"></param>
        /// <param name="compare">大于compare，返回data值的string形式</param>
        /// <returns></returns>
        public static string ToNumString(this int data, double compare = 0, string defaultValue = "")
        {
            if (data > compare)
            {
                return data.ToString();
            }
            else
            {
                return defaultValue;
            }
        }

        /// <summary>
        /// 转换为bool类型
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static bool ToBool(this object data)
        {
            if (data.IsEmpty())
            {
                return false;
            }

            if (!Boolean.TryParse(data.ToString(), out bool result))
            {
                return data.ToString().Equals("1");
            }

            return result;
        }

        /// <summary>
        /// 格式化毫秒显示格式
        /// </summary>
        /// <param name="millisecond"></param>
        /// <returns></returns>
        public static string FormatTimeMillisecond(this long millisecond)
        {
            DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0);
            dateTime = dateTime.AddMilliseconds(millisecond);
            return dateTime.ToString("HH:mm:ss");
        }

        /// <summary>
        /// 负无穷或者正无穷转为默认值
        /// </summary>
        /// <param name="data"></param>
        /// <param name="value">默认值</param>
        /// <returns></returns>
        public static float InfinityFloatToDefault(this float data, float value)
        {
            if (float.IsNegativeInfinity(data))
            {
                return value;
            }

            if (float.IsPositiveInfinity(data))
            {
                return value;
            }

            return data;
        }

        /// <summary>
        /// 转换为时间格式
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static DateTime? ToDateTimeOrNull(this object data)
        {
            if (!data.IsEmpty())
            {
                if (DateTime.TryParse(data.ToString(), out DateTime dateTime))
                {
                    return dateTime;
                }
            }

            return null;
        }

        /// <summary>
        /// 格式化时间日期显示
        /// </summary>
        /// <param name="data"></param>
        /// <param name="format"></param>
        /// <returns></returns>
        public static string ToDateTimeString(this object data, string format)
        {
            if (!data.IsEmpty())
            {
                if (DateTime.TryParse(data.ToString(), out DateTime dateTime))
                {
                    return dateTime.ToString(format);
                }
            }

            return data.ToString();
        }

        /// <summary>
        /// 转换为时间格式
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static DateTime ToDateTime(this object data)
        {
            if (!data.IsEmpty())
            {
                if (DateTime.TryParse(data.ToString(), out DateTime dateTime))
                {
                    return dateTime;
                }
            }

            return DateTime.MinValue;
        }

        /// <summary>
        /// 转换为时间格式
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static DateTime ToDateTime(this object data, string format)
        {
            if (!data.IsEmpty())
            {
                IFormatProvider ifp = new CultureInfo(CultureInfo.DefaultThreadCurrentCulture?.Name, true);
                if (DateTime.TryParseExact(data.ToString(), format, ifp, DateTimeStyles.None, out DateTime dateTime))
                {
                    return dateTime;
                }
            }

            return DateTime.MinValue;
        }

        /// <summary>
        /// 时间换算为十分之一毫秒
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        public static string ToOneTenthOfMilliseconds(this DateTime dateTime)
        {
            return $"{(dateTime.Hour * 3600000 + dateTime.Minute * 60000 + dateTime.Second * 1000 + dateTime.Millisecond) / 10}";
        }

        /// <summary>
        /// 转换为对应的枚举值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <returns></returns>
        // public static T ToEnum<T>(this object data) where T : Enum
        public static T ToEnum<T>(this object data)
        {
            if (!data.IsEmpty())
            {
                Type type = typeof(T);

                try
                {
                    return (T)Enum.Parse(type, data.ToString());
                }
                catch (Exception)
                {
                    return default(T);
                }
            }
            else
            {
                return default(T);
            }
        }

    }
}
